package com.ruibang.glass.produce.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.domain.quality.MaterialLotItem;
import com.ruibang.glass.produce.constant.Constants;
import com.ruibang.glass.produce.domain.req.TrRecordReq;
import com.ruibang.glass.produce.domain.resp.ProductionRecordBase;
import com.ruibang.glass.produce.domain.resp.TrProductionRecord;
import com.ruibang.glass.produce.entity.FatalDefect;
import com.ruibang.glass.produce.entity.ProductionRecord;
import com.ruibang.glass.produce.entity.TotalEquData;
import com.ruibang.glass.produce.feign.QualityApi;
import com.ruibang.glass.produce.mapper.ProductionRecordMapper;
import com.ruibang.glass.produce.service.ProductionRecordService;
import com.ruibang.glass.produce.util.ExcelStyleUtils;
import com.teaming.cloud.framework2.common.model.ResultBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: songJinKang
 * @CreateTime: 2023-11-29  13:58
 * @Description: TODO
 * @Version: 1.0
 */

@Slf4j
@Service
public class ProductionRecordServiceImpl extends ServiceImpl<ProductionRecordMapper, Object> implements ProductionRecordService {

    @Autowired
    private QualityApi qualityApi;

    @Override
    public ResultBody getCurrentTimeTrRecord() {
        ProductionRecordBase productionRecordBase = new ProductionRecordBase();
        StringBuilder recordStr = new StringBuilder();
        //获取当前时间
        LocalDateTime currentTime = LocalDateTime.now().minusHours(1);
        LocalTime localTime = currentTime.toLocalTime();
        String startTimeStr = LocalTime.of(localTime.getHour(), 0, 0).toString();
        String endTimeStr = LocalTime.of(LocalTime.now().getHour(), 0, 0).toString();
        String timeStr = startTimeStr + "-" + endTimeStr;
        recordStr.append(timeStr).append(" 冷端生产情况汇报：\n");


        log.error("{}-{}-{}-{}", currentTime.getYear(), currentTime.getMonthValue(), currentTime.getDayOfMonth(), currentTime.getHour());
        List<ProductionRecord> productionRecords = baseMapper.getCurrentTimeTrRecord(currentTime.getYear(), currentTime.getMonthValue(), currentTime.getDayOfMonth(), currentTime.getHour());
        if (CollectionUtils.isNotEmpty(productionRecords)) {
            //直投良品
            long ztNum = productionRecords.stream().filter(e -> e.getGid8() == 258 && e.getGid9() == 0).count();
            //A型架良品
            long axjNum = productionRecords.stream().filter(e -> e.getGid8() == 512 && e.getGid9() == 0).count();
            //再清洗返投
            long zqxNum = productionRecords.stream().filter(e -> e.getGid9() == 16).count();

//            -------直投良品-----

            //直投良品t1
            long ztt1Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 2049 || e.getGid12() == 2050 || e.getGid12() == 2052 || e.getGid12() == 2056 || e.getGid12() == 2064 || e.getGid12() == 2080) && e.getGid8() == 258 && e.getGid9() == 0).count();
            //直投良品t2
            long ztt2Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 513 || e.getGid12() == 514 || e.getGid12() == 516 || e.getGid12() == 520 || e.getGid12() == 528 || e.getGid12() == 544) && e.getGid8() == 258 && e.getGid9() == 0).count();
            //直投良品t3
            long ztt3Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 1025 || e.getGid12() == 1026 || e.getGid12() == 1028 || e.getGid12() == 1032 || e.getGid12() == 1040 || e.getGid12() == 1056) && e.getGid8() == 258 && e.getGid9() == 0).count();
            //直投良品NG
            List<ProductionRecord> ztNg = productionRecords.stream().filter(e ->
                    (e.getGid12() == 257 || e.getGid12() == 258 || e.getGid12() == 260 || e.getGid12() == 264 || e.getGid12() == 272 || e.getGid12() == 288) && e.getGid8() == 258 && e.getGid9() == 0).collect(Collectors.toList());
            //直投良品reclean
            long ztCleanCount = productionRecords.stream().filter(e ->
                    (e.getGid12() == 4097 || e.getGid12() == 4098 || e.getGid12() == 4100 || e.getGid12() == 4104 || e.getGid12() == 4112 || e.getGid12() == 4128) && e.getGid8() == 258 && e.getGid9() == 0).count();
            //直投良品抽检
            long ztCjNum = productionRecords.stream().filter(
                    e -> e.getGid12() == 0 && e.getGid8() == 258 && e.getGid9() == 0 && ("CJ1".equals(e.getPort()) || "CJ2".equals(e.getPort()))).count();

//            -------A型架良品------

            //A型架良品t1
            long axjT1Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 2049 || e.getGid12() == 2050 || e.getGid12() == 2052 || e.getGid12() == 2056 || e.getGid12() == 2064 || e.getGid12() == 2080) && e.getGid8() == 512 && e.getGid9() == 0).count();
            //A型架良品t2
            long axjT2Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 513 || e.getGid12() == 514 || e.getGid12() == 516 || e.getGid12() == 520 || e.getGid12() == 528 || e.getGid12() == 544) && e.getGid8() == 512 && e.getGid9() == 0).count();
            //A型架良品t3
            long axjT3Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 1025 || e.getGid12() == 1026 || e.getGid12() == 1028 || e.getGid12() == 1032 || e.getGid12() == 1040 || e.getGid12() == 1056) && e.getGid8() == 512 && e.getGid9() == 0).count();
            //A型架良品Ng
            List<ProductionRecord> axjNg = productionRecords.stream().filter(e ->
                    (e.getGid12() == 257 || e.getGid12() == 258 || e.getGid12() == 260 || e.getGid12() == 264 || e.getGid12() == 272 || e.getGid12() == 288) && e.getGid8() == 512 && e.getGid9() == 0).collect(Collectors.toList());
            //A型架良品reclean
            long axjCleanNum = productionRecords.stream().filter(e ->
                    (e.getGid12() == 4097 || e.getGid12() == 4098 || e.getGid12() == 4100 || e.getGid12() == 4104 || e.getGid12() == 4112 || e.getGid12() == 4128) && e.getGid8() == 512 && e.getGid9() == 0).count();
            //A型架良品抽检
            long axjCjNum = productionRecords.stream().filter(
                    e -> e.getGid12() == 0 && e.getGid8() == 512 && e.getGid9() == 0 && ("CJ1".equals(e.getPort()) || "CJ2".equals(e.getPort()))).count();

//            ----------成品返投------

            //成品返投t1
            long cpFtT1Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 2049 || e.getGid12() == 2050 || e.getGid12() == 2052 || e.getGid12() == 2056 || e.getGid12() == 2064 || e.getGid12() == 2080) && e.getGid9() == 16).count();
            //成品返投t2
            long cpFtT2Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 513 || e.getGid12() == 514 || e.getGid12() == 516 || e.getGid12() == 520 || e.getGid12() == 528 || e.getGid12() == 544) && e.getGid9() == 16).count();
            //成品返投t3
            long cpFtT3Num = productionRecords.stream().filter(e ->
                    (e.getGid12() == 1025 || e.getGid12() == 1026 || e.getGid12() == 1028 || e.getGid12() == 1032 || e.getGid12() == 1040 || e.getGid12() == 1056) && e.getGid9() == 16).count();
            //成品返投Ng
            List<ProductionRecord> cpFtNg = productionRecords.stream().filter(e ->
                    (e.getGid12() == 257 || e.getGid12() == 258 || e.getGid12() == 260 || e.getGid12() == 264 || e.getGid12() == 272 || e.getGid12() == 288) && e.getGid9() == 16).collect(Collectors.toList());
            //成品返投reclean
            long cpFtCleanNum = productionRecords.stream().filter(e ->
                    (e.getGid12() == 4097 || e.getGid12() == 4098 || e.getGid12() == 4100 || e.getGid12() == 4104 || e.getGid12() == 4112 || e.getGid12() == 4128) && e.getGid9() == 16).count();
            //成品返投抽检
            long cpFtCjNum = productionRecords.stream().filter(
                    e -> e.getGid12() == 0 && e.getGid9() == 16 && ("CJ1".equals(e.getPort()) || "CJ2".equals(e.getPort()))).count();

            //缺陷
            List<ProductionRecord> defect = new ArrayList<>();
            defect.addAll(ztNg);
            defect.addAll(axjNg);
            defect.addAll(cpFtNg);
            List<String> glassIds = defect.stream().map(e -> e.getGlassId().substring(6)).collect(Collectors.toList());
            List<TotalEquData> totalEquData = baseMapper.getDefectInfo(glassIds);

            //获取致命缺陷对应关系
            List<FatalDefect> fatalDefectList = baseMapper.getFatalDefect();

            //记录类容拼接
            long coldNum = ztNum + zqxNum + axjNum;
            recordStr.append("冷端共投入").append(coldNum).append("片，（");
            if (ztNum > 0) {
                recordStr.append("直投良品").append(ztNum).append("片，");
            }
            if (zqxNum > 0) {
                recordStr.append("再清洗返投").append(zqxNum).append("片，");
            }
            if (axjNum > 0) {
                recordStr.append("A型架良品").append(axjNum).append("片");
            }
            recordStr.append("）\n");


            if (ztNum > 0) {
                //良品包装数
                long lpBzNum = ztt1Num + ztt2Num + ztt3Num;
                recordStr.append("检查直投良品").append(ztNum).append("片，良品包装").append(lpBzNum).append("片（");
                processClassification(recordStr, ztt1Num, ztt2Num, ztt3Num);
//            if (ztCleanCount > 0) {
//                recordStr.append("再清洗:").append(ztCleanCount).append("片");
//            }
                recordStr.append("）,成品良率").append(processDecimal(((double) lpBzNum / ztNum) * 100, Constants.TWO_INT)).append("%\n");

                if (ztCleanCount > 0) {
                    recordStr.append("再清洗包装数").append(ztCleanCount).append("片，占比").append(processDecimal(((double) ztCleanCount / ztNum) * 100, Constants.TWO_INT)).append("%\n");
                }

                //主要不良分析
                String defectStr = processDefect(totalEquData, ztNg, fatalDefectList, ztNum);
                if (StringUtils.isNotBlank(defectStr)) {
                    recordStr.append(defectStr);
                }
            }


            //A型架
            if (axjNum > 0) {
                long alpBzNum = axjT1Num + axjT2Num + axjT3Num;//A型架良品包装数
                recordStr.append("A型架直投良品").append(axjNum).append("片，良品包装").append(alpBzNum).append("片（");
                processClassification(recordStr, axjT1Num, axjT2Num, axjT3Num);
//            if (axjCleanNum > 0) {
//                recordStr.append("再清洗:").append(axjCleanNum).append("片");
//            }
                recordStr.append("）,A型架成品良率").append(processDecimal(((double) alpBzNum / axjNum) * 100, Constants.TWO_INT)).append("%\n");
                if (ztCleanCount > 0) {
                    recordStr.append("再清洗包装数").append(axjCleanNum).append("片，占比").append(processDecimal(((double) axjCleanNum / axjNum) * 100, Constants.TWO_INT)).append("%\n");
                }

                //主要不良分析
                String defectStr = processDefect(totalEquData, axjNg, fatalDefectList, ztNum);
                if (StringUtils.isNotBlank(defectStr)) {
                    recordStr.append(defectStr);
                }
            }


            //再清洗返投
            if (zqxNum > 0) {
                long zqxFtNum = cpFtT1Num + cpFtT2Num + cpFtT3Num;
                recordStr.append("再清洗返投品").append(zqxNum).append("片，良品包装").append(zqxFtNum).append("片（");
                processClassification(recordStr, cpFtT1Num, cpFtT2Num, cpFtT3Num);
//            if (cpFtCleanNum > 0) {
//                recordStr.append("再清洗:").append(axjCleanNum).append("片");
//            }
                double zqxFt = ((double) zqxFtNum / zqxNum) * 100;
                recordStr.append("），再清洗返投率").append(processDecimal(Double.isNaN(zqxFt) ? 0 : zqxFt, Constants.TWO_INT)).append("%\n");
                if (cpFtCleanNum > 0) {
                    recordStr.append("再清洗包装数").append(cpFtCleanNum).append("片，占比").append(processDecimal(((double) cpFtCleanNum / zqxNum) * 100, Constants.TWO_INT)).append("%\n");
                }

                //主要不良分析
                String defectStr = processDefect(totalEquData, cpFtNg, fatalDefectList, ztNum);
                if (StringUtils.isNotBlank(defectStr)) {
                    recordStr.append(defectStr);
                }
            }

            //抽检
            long cjNum = ztCjNum + axjCjNum + cpFtCjNum;
            if (cjNum > 0) {
                recordStr.append("抽检数").append(cjNum).append("片，").append("抽检占比：").append(processDecimal(((double) cjNum / coldNum) * 100, Constants.TWO_INT)).append("%");
            }


            log.error("size:{}", totalEquData.size());
        }

        String content = recordStr.toString().replace("（）", "").replace("、）", "）").replace("，）", "）");

        productionRecordBase.setContent(content);
        return ResultBody.success(productionRecordBase);
    }


    private void processClassification(StringBuilder recordStr, long t1Num, long t2Num, long t3Num) {
        if (t1Num > 0) {
            recordStr.append("T1：").append(t1Num).append("片、");
        }
        if (t2Num > 0) {
            recordStr.append("T2：").append(t2Num).append("片、");
        }
        if (t3Num > 0) {
            recordStr.append("T3：").append(t3Num).append("片、");
        }
    }


    private String processDecimal(double value, int num) {
        return String.format("%." + num + "f", value);
    }

    public static void main(String[] args) {
        System.out.println("Manual: ADG, Auto: BevelChip-EIS".split(",")[0].split(":")[1].trim());
    }

    public String processDefect(List<TotalEquData> totalEquData, List<ProductionRecord> productionRecord, List<FatalDefect> fatalDefectList, long ztLpNum) {
        StringBuilder stringBuilder = new StringBuilder();
        if (CollectionUtils.isNotEmpty(productionRecord) && CollectionUtils.isNotEmpty(totalEquData) && CollectionUtils.isNotEmpty(fatalDefectList)) {
            Map<String, String> glassIdMap = productionRecord.stream().map(e -> e.getGlassId().substring(6)).collect(Collectors.toMap(e -> e, e -> e));
            List<TotalEquData> filter = totalEquData.stream().filter(e -> {
                String defectData = glassIdMap.get(e.getCustomerPanelId());
                if (StringUtils.isNotBlank(defectData)) {
                    String comment = e.getComment();
                    if (comment.contains("Auto:") && comment.contains("Manual:")) {
                        e.setComment(e.getComment().split(",")[0].split(":")[1].trim());
                    }
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(filter)) {
                Map<String, List<TotalEquData>> defectMap = filter.stream().collect(Collectors.groupingBy(TotalEquData::getComment));
                int count = 1;
                for (FatalDefect fatalDefect : fatalDefectList) {
                    List<TotalEquData> defectData = defectMap.get(fatalDefect.getCode());
                    if (CollectionUtils.isNotEmpty(defectData)) {
                        String ratio = processDecimal(((double) defectData.size() / ztLpNum) * 100, 2);
                        stringBuilder.append(count).append(".").append(fatalDefect.getName()).append("不良").append(defectData.size()).append("片，占比").append(ratio).append("%\n");
                        count++;
                    }
                }
            }
        }
        return stringBuilder.toString();
    }


    @Override
    public IPage<TrProductionRecord> pageQuery(TrRecordReq trRecordReq) {
        if (trRecordReq.getStartTime() != null && trRecordReq.getEndTime() != null) {
            trRecordReq.setEndTs(trRecordReq.getEndTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            trRecordReq.setStartTs(trRecordReq.getStartTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
        IPage<TrProductionRecord> page = baseMapper.pageQuery(new Page<>(trRecordReq.getPageNo(), trRecordReq.getPageSize()), trRecordReq);
        if (page != null && CollectionUtils.isNotEmpty(page.getRecords())) {
            //获取热端玻璃ID
            List<TrProductionRecord> data = page.getRecords();
            List<String> newIds = data.stream().map(TrProductionRecord::getColdGlassId).collect(Collectors.toList());
            ResultBody<Map<String, String>> resultBody = qualityApi.getColdIdMappingHotId(newIds);
            if (resultBody != null && resultBody.getData() != null && resultBody.getData().size() > 0) {
                Map<String, String> map = resultBody.getData();
                for (TrProductionRecord trProductionRecord : data) {
                    String hotId = map.get(trProductionRecord.getColdGlassId());
                    if (StringUtils.isNotBlank(hotId) && hotId.startsWith(Constants.HOT_GLASS_ID_PREFIX)) {
                        trProductionRecord.setGlassId(map.get(trProductionRecord.getColdGlassId()));
                    }
                }
            }
            //获取托盘号
            List<String> coldIds = data.stream().map(TrProductionRecord::getColdGlassId).distinct().collect(Collectors.toList());
            List<MaterialLotItem> materialLotItems = baseMapper.getLotItemInfo(coldIds);
            if (CollectionUtils.isNotEmpty(materialLotItems)) {
                Map<String, MaterialLotItem> materialLotItemMap = materialLotItems.stream().collect(Collectors.toMap(MaterialLotItem::getGlassCode, e -> e));
                for (TrProductionRecord trProductionRecord : data) {
                    MaterialLotItem materialLotItem = materialLotItemMap.get(trProductionRecord.getColdGlassId());
                    if (materialLotItem != null && StringUtils.isNotBlank(materialLotItem.getBindId())) {
                        String bindId = materialLotItem.getBindId();
                        try {
                            String containerCode = bindId.substring(0, 13);
                            trProductionRecord.setPalletNumber(containerCode);
                        } catch (Exception e) {
                            log.error("容器编号截取失败：{}", e.getMessage());
                        }
                    }
                }
            }
        }
        return page;
    }

    @Override
    public void export(TrRecordReq trRecordReq, HttpServletResponse response) {
        trRecordReq.setPageNo(-1);
        trRecordReq.setPageSize(-1);
        IPage<TrProductionRecord> page = this.pageQuery(trRecordReq);
        if (page != null && CollectionUtils.isNotEmpty(page.getRecords())) {
            List<TrProductionRecord> trProductionRecordList = page.getRecords();
            try {
                EasyExcel.write(response.getOutputStream(), TrProductionRecord.class)
                        .registerWriteHandler(ExcelStyleUtils.createTableStyle())
                        .sheet("投入生产记录").doWrite(trProductionRecordList);
            } catch (IOException e) {
                log.error("数据导出失败：{}", e.getMessage());
            }
        }
    }

}
